﻿using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using NUnit.Framework;
using UnitTestUtils.UI;
using AppToolkit.WPF.Controls;
using System.Windows.Documents;
using System.IO;
using System.Windows;
using AppToolkit.WPF.Controls.Utils;
using System.Windows.Threading;

namespace AppToolkit.WPF.Tests.Controls
{
    [TestFixture]
    public class RichTextEditorTests
    {
        UIHost _host;
        RichTextEditorTestWindow _target;

        #region Setup / Teardown
        [SetUp]
        public void Setup()
        {
            _target = new RichTextEditorTestWindow();
            _target.Width = 200;
            _target.Height =200;
            
            _host = UIHost.Create(_target);
        }

        [TearDown]
        public void Dispose()
        {
            _target = null;
            _host = null;
            UnitTestUtils.UI.UITestHelper.CleanupDispatcher();
        }
        #endregion

        [Test, RequiresSTA, Explicit]
        public void Interactive_test()
        {
            _host.ShowDialog();
        }

        [Test, RequiresSTA]
        public void Converter_property_set_to_NullConverter_by_default()
        {
            var rtEdit = WPFTreeUtil.FindItem<RichTextEditor>(_target);

            var result = rtEdit.Converter;
            
            Assert.IsNotNull(result);
            Assert.AreEqual(typeof(NullConverter), result.GetType());
        }

        [Test, RequiresSTA]
        public void Setting_HtmlXamlConverter_produces_html_output()
        {
            const string expectedText = "this is the bold test";

            var rtEdit = WPFTreeUtil.FindItem<RichTextEditor>(_target);

            rtEdit.Converter = new HtmlXamlConverter();
            rtEdit.Text = string.Format("<b>{0}</b>", expectedText);

            var ctrl = WPFTreeUtil.FindItem<System.Windows.Controls.RichTextBox>(rtEdit);

            string txt = getText(ctrl);
            Assert.IsTrue(txt.Contains(expectedText));
        }

        [Test, RequiresSTA]
        public void Setting_empty_string_to_Text_property()
        {
            var rtEdit = WPFTreeUtil.FindItem<RichTextEditor>(_target);
            rtEdit.Converter = new HtmlXamlConverter();
            
            bool docUpdated = false;
            rtEdit.DocumentUpdated += (s, a) => docUpdated = true;

            var ctrl = WPFTreeUtil.FindItem<System.Windows.Controls.RichTextBox>(rtEdit);

            // set some text to the control
            Clipboard.SetText("Some test text.");
            ctrl.Paste();
            rtEdit.UpdateFlowDocument();
            
            // set Text property to empty string
            rtEdit.Text = "";

            Dispatcher.CurrentDispatcher.Flush();

            // check if control contents has been cleared.
            // remark: checking the control contents does not work, because it is
            //         somehow done async.
            Assert.IsTrue(docUpdated);
        }

        [Test, RequiresSTA]
        public void UpdateFlowDocument_triggers_sync_from_flowdocument_to_text_property()
        {
            const string expectedText = "this is the bold test";

            var rtEdit = WPFTreeUtil.FindItem<RichTextEditor>(_target);

            rtEdit.Converter = new HtmlXamlConverter();

            var ctrl = WPFTreeUtil.FindItem<System.Windows.Controls.RichTextBox>(rtEdit);
            Clipboard.SetText(expectedText);
            ctrl.Paste();

            rtEdit.UpdateFlowDocument();

            Assert.IsTrue(rtEdit.Text.Contains(expectedText));
        }

        #region Helper
        private static string getText(System.Windows.Controls.RichTextBox ctrl)
        {
            string txt;
            TextRange tr = new TextRange(ctrl.Document.ContentStart,
                               ctrl.Document.ContentEnd);

            using (MemoryStream ms = new MemoryStream())
            {
                tr.Save(ms, DataFormats.Xaml);
                txt = ASCIIEncoding.Default.GetString(ms.ToArray());
            }
            return txt;
        } 
        #endregion
    }
}
